<?php

namespace app\admin\controller\file;

use app\admin\model\UM;
use app\common\service\processes\ProcessInterface;
use ShidianUtil\Thinkphp\Response\ApiResponse;
use ShidianUtil\Utils\StringUtil;
use think\exception\ValidateException;
use think\facade\Config;
use think\facade\Filesystem;
use think\file\UploadedFile;
use think\Request;

/**
 * 静态资源文件
 * Class File
 * @package app\file\controller
 * @link https://www.kancloud.cn/manual/thinkphp6_0/1037509
 */
class File
{
    protected Request $request;

    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    // 动态图片
    public function read()
    {
        $pathinfo = $this->request->pathinfo();
        $get = $this->request->get();

        $config = Config::get('fileprocess', []);
        $delimiter = $config['delimiter'] ?? '-';

        $pathinfo = pathinfo($pathinfo);

        $ext = $pathinfo['extension'] ?? '';
        if (StringUtil::contains($ext, $delimiter)) {
            list($ext, $style) = explode($delimiter, $ext);

            $originPath = $pathinfo['dirname'] . '/' . $pathinfo['filename'] . '.' . $ext;
            $savePath = $pathinfo['dirname'] . '/' . $pathinfo['basename'];

            $processes = $config['processes'] ?? [];
            foreach ($processes as $process) {
                $processExt = $process['ext'] ?? [];
                if (in_array($ext, $processExt)) {

                    $handler = $process['driver'] ?? null;

                    $success = $this->getProcess($handler)->process($originPath, $savePath, $process['styles'][$style] ?? []);

                    if ($success) {
                        return download($savePath, pathinfo($savePath, PATHINFO_BASENAME));
                    }

                    return ApiResponse::fail('图片不存在或无法获取');
                }
            }
        }

        return ApiResponse::fail('文件不存在');
    }

    private function getProcess($type): ProcessInterface
    {
        return app_instance(ProcessInterface::class, $type, '', 'Process');
    }

    /**
     * 上传文件
     * @param \app\admin\model\UM|null $user
     * @return ApiResponse
     */
    public function save(UM $user): ApiResponse
    {
        $request = $this->request;

        // 1.文件上传后，返回原图url
        // 2.如果客户端需要访问缩略图，那么客户端在url后面加参数，表示需要对图片处理
        // 3.单独的图片请求处理，nginx把请求参数转换成对应路径转发，如果文件不存在，那么就转发给php程序处理生成，然后重定向读取

        $fileType = $request->param('fileType');

        $file = $request->file();

        if (isset($file['file'])) {

            $this->validateFile($fileType, $file['file']);

            $data = $this->putFile($fileType, $file['file']);

        } elseif (isset($file['files']) && is_array($file['files'])) {

            foreach ($file['files'] as $item) {
                $this->validateFile($fileType, $item);
            }

            $data = [];
            foreach ($file['files'] as $key => $item) {
                $data[$key] = $this->putFile($fileType, $item);
            }
        } else {
            throw new ValidateException('请上传文件');
        }

        return ApiResponse::success($data);
    }

    // 验证文件
    private function validateFile($fileType, $file)
    {
        if (!$file instanceof \think\File) {
            throw new ValidateException('请上传正确的文件');
        }

        // 读取不同类型文件的验证规则
        $validate = Config::get('fileupload.' . $fileType, null);
        if (is_null($validate)) {
            throw new ValidateException('错误的文件类型');
        }

        // 验证文件
        if (not_blank($validate)) {
            validate(['file' => $validate])->check(['file' => $file]);
        }

    }

    // 保存文件
    private function putFile($fileType, UploadedFile $file)
    {
        // 生成路径
        $ext = $file->extension();
        $size = $file->getSize();

        $path = '/' . date('Y') . '/' . date('m') . '/' . date('d');
        $name = uuid(22);
        $fileName = "$name.$ext";

        // 超过一定大小的图片进行压缩处理
        if ($fileType == 'image') {

            //

        }

        // 保存文件
        Filesystem::putFileAs($path, $file, $fileName);

        $showPath = Filesystem::url($path) . '/' . $fileName;

        // TODO 后期完善后改成图片服务的域名
        $fullPath = $this->request->domain() . $showPath;

        return [
            'path' => $showPath,
            'fullPath' => $fullPath,
            'ext' => $ext,
            'size' => $size,
        ];
    }

}
